package cn.tedu.charging.device.dao.repository.impl;

import cn.tedu.charging.device.dao.repository.AbstractStationCacheRepository;
import cn.tedu.charging.device.dao.repository.StationCacheRepository;
import cn.tedu.charging.device.pojo.po.StationCanalPO;
import cn.tedu.charging.device.pojo.po.StationPO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.Circle;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.GeoResult;
import org.springframework.data.geo.GeoResults;
import org.springframework.data.redis.connection.RedisCommands;
import org.springframework.data.redis.connection.RedisGeoCommands;
import org.springframework.data.redis.core.GeoOperations;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Repository;

import java.math.BigDecimal;
import java.util.*;


/**
 * 位置信息 GEO
 * 基本信息 Hash
 *
 * Map<bigKey,Map<hashKey,value>>
 *
 * bigKey ?
 * 站点id stationId
 * hashKey ?
 * 站属性名 stationName
 * value  ?
 * 站属性值 充的快充电站
 *
 * Map<bigKey,Map<hashKey,value>> map = new HashMap();
 *
 * Map<hashKey,value> small = new HashMap();
 *
 *              站属性名      站属性值
 * small.put("stationName","充的快充电站");
 * small.put("status","营业中");
 * small.put("gunNum",100);
 *
 * map.put("stationId",map);
 *
 *
 * Map<bigKey,Map<hashKey,value>> map = new HashMap();
 *
 * Map<hashKey,value> small = new HashMap();
 *              站id        站完整信息
 * small.put("stationId5","stationPO");
 * small.put("stationId4","stationPO");
 * small.put("stationId8","stationPO");
 *
 * map.put("stationHash",map);
 *
 * PO属性拆开的方式   一个站 一个Hash  独享
 * Redis的 Hash
 * 可以 通过大key 和 HashKey 直接 <获取> 到对应 value                    容易复用
 * 可以 通过大key 和 HashKey 直接 <修改> 到对应 value                    容易修改
 * 如果 站的数据量过大 redis 可以采用 分片技术 不同的站 在不同的分片          容易扩展
 *
 * PO属性不拆开方式   所有站 一个Hash 共享
 *  数量小
 *  容易理解
 *
 *
 */
@Slf4j
@Repository("GeoAndShareHash")
public class StationCacheGeoAndShareHashRepositoryImpl
        extends AbstractStationCacheRepository
        implements StationCacheRepository {

    @Autowired
    private RedisTemplate redisTemplate;


    @Override
    public RedisTemplate getRedisTemplate() {
        return redisTemplate;
    }

    @Override
    public void saveAllStation(List<StationPO> stationPOs) {
        //保存映射关系 位置 和 站点id
        saveLocationByGEOAndMemberIsId(stationPOs);
        //保存基本信息到Hash
        saveStationInfoByShareHash(stationPOs);
    }

    /**
     * 保存基本信息到Hash 所有的充电站 存储 在一个hash中
     * @param stationPOs
     */
    private void saveStationInfoByShareHash(List<StationPO> stationPOs) {
        HashOperations hashOperations = redisTemplate.opsForHash();
        String bigKey = "station_info_hash_share";
        Map<String,StationPO> stationPOMap = new HashMap<>();
        for (StationPO stationPO : stationPOs) {
            String hashKey = String.valueOf(stationPO.getId());
            stationPOMap.put(hashKey,stationPO);
        }
        hashOperations.putAll(bigKey,stationPOMap);
    }

    @Override
    public List<StationPO> search(Double lng, Double lat, Double radius) {
        GeoOperations geoOperations = redisTemplate.opsForGeo();

        Circle circle = getCircle(lng, lat, radius);

        GeoResults<RedisCommands.GeoLocation<Integer>>
                results = geoOperations.radius("stations_mapping", circle);

        List<StationPO> stationPOS = new ArrayList<>();
        //先通过用户的 位置和范围 查出 充电站id 列表

        for (GeoResult<RedisGeoCommands.GeoLocation<Integer>> result : results) {
            Distance distance = result.getDistance();
            log.debug("距离:{}",distance);
            //GeoResult 里的具体的数据 用 content
            RedisGeoCommands.GeoLocation<Integer> content =
                    result.getContent();
            log.debug("content:{}",content);
            //name 表示的是 GEOADD  是 member stationId
            Integer stationId = content.getName();

            StationPO stationPO = getStationInfoById(String.valueOf(stationId));

            stationPOS.add(stationPO);
        }
        return stationPOS;
    }

    @Override
    public void update(StationCanalPO stationCanalPO) {

    }

    @Override
    public void insert(StationCanalPO stationCanalPO) {

    }

    @Override
    public void delete(StationCanalPO stationCanalPO) {

    }


    @Override
    public StationPO getStationInfoById(String stationId){
        String bigKey = "station_info_hash_share";
        // HashOperations<H, HK, HV>
        HashOperations<String,String,StationPO>
                hashOperations = redisTemplate.opsForHash();

        //1>> 通过 大key 和 HashKey 直接 <获取> 到对应 value
        //Object o = hashOperations.get(bigKey, "stationId");

        //2>> 通过 大key 和 HashKey列表 直接 <获取> 到对应 value列表
        //List<String> hashKeys = Arrays.asList("1", "2");
        //List<Object> hashValues = hashOperations.multiGet(bigKey, hashKeys);

        //3>> 通过 大key 查询 小map
        //Map<String,Object> smallMap = hashOperations.entries(bigKey);
        return hashOperations.get(bigKey,stationId);
    }


}
